"""
数据存储模块
基于JSON文件的数据持久化
"""

import json
import os
import time
import asyncio
from typing import Dict, List, Any, Optional
from pathlib import Path
from dataclasses import dataclass, asdict
from .config import config


@dataclass
class ModelInfo:
    """模型信息数据类"""
    id: str
    name: str
    version: str
    model_type: str
    description: str
    author: str
    size: str
    upload_time: float
    last_update: float
    status: str
    download_url: str
    checksum: str
    server_id: str
    tags: List[str]
    requirements: Dict[str, str]
    metrics: Dict[str, Any]
    
    def to_dict(self) -> Dict[str, Any]:
        return asdict(self)
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'ModelInfo':
        return cls(**data)


@dataclass
class SubscriptionRecord:
    """订阅记录数据类"""
    id: str
    client_id: str
    client_name: str
    model_name: str
    model_version: str
    server_id: str
    subscribed_at: float
    last_checked: float
    status: str  # 'active', 'paused', 'cancelled'
    auto_update: bool
    notification_channels: List[str]
    callback_url: Optional[str]
    
    def to_dict(self) -> Dict[str, Any]:
        return asdict(self)
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'SubscriptionRecord':
        return cls(**data)


@dataclass
class SubscriptionServer:
    """订阅服务器数据类"""
    id: str
    name: str
    url: str
    api_key: Optional[str]
    status: str  # 'online', 'offline', 'error'
    last_check: Optional[float]
    check_interval: int
    consecutive_errors: int
    
    def to_dict(self) -> Dict[str, Any]:
        return asdict(self)
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'SubscriptionServer':
        return cls(**data)


@dataclass
class ClientInfo:
    """客户端信息数据类"""
    id: str
    client_id: str
    client_name: str
    hostname: str
    ip_address: str
    port: int
    version: str
    capabilities: List[str]
    description: str
    contact_info: Optional[str]
    registered_at: float
    last_seen: float
    status: str  # 'online', 'offline', 'error'
    
    def to_dict(self) -> Dict[str, Any]:
        return asdict(self)
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'ClientInfo':
        return cls(**data)


@dataclass
class ModelStatusInfo:
    """模型状态信息数据类"""
    id: str
    client_id: str
    model_name: str
    model_type: str
    model_size: Optional[str]
    model_version: Optional[str]
    status: str
    file_path: Optional[str]
    file_size: Optional[int]
    upload_time: Optional[float]
    last_used: Optional[float]
    usage_count: int
    performance_metrics: Dict[str, Any]
    error_message: Optional[str]
    system_info: Dict[str, Any]
    reported_at: float
    last_updated: float
    
    def to_dict(self) -> Dict[str, Any]:
        return asdict(self)
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'ModelStatusInfo':
        return cls(**data)


class JSONStorage:
    """JSON文件存储基类"""
    
    def __init__(self, file_path: str):
        self.file_path = Path(file_path)
        self.file_path.parent.mkdir(parents=True, exist_ok=True)
        self._lock = asyncio.Lock()
        
    async def load(self) -> Dict[str, Any]:
        """加载数据"""
        async with self._lock:
            if not self.file_path.exists():
                return {}
                
            try:
                with open(self.file_path, 'r', encoding='utf-8') as f:
                    return json.load(f)
            except Exception as e:
                print(f"Error loading {self.file_path}: {e}")
                return {}
                
    async def save(self, data: Dict[str, Any]):
        """保存数据"""
        async with self._lock:
            try:
                # 创建临时文件
                temp_path = self.file_path.with_suffix('.tmp')
                
                with open(temp_path, 'w', encoding='utf-8') as f:
                    json.dump(data, f, indent=2, ensure_ascii=False)
                
                # 原子性替换
                temp_path.replace(self.file_path)
                
            except Exception as e:
                print(f"Error saving {self.file_path}: {e}")
                raise


class DataManager:
    """数据管理器"""
    
    def __init__(self):
        storage_config = config.get_storage_config()
        data_dir = storage_config.get('data_dir', 'data')
        
        # 确保数据目录存在
        Path(data_dir).mkdir(parents=True, exist_ok=True)
        
        # 初始化各个存储
        self.models_storage = JSONStorage(
            os.path.join(data_dir, storage_config.get('models_file', 'models.json'))
        )
        self.subscriptions_storage = JSONStorage(
            os.path.join(data_dir, storage_config.get('subscriptions_file', 'subscriptions.json'))
        )
        self.servers_storage = JSONStorage(
            os.path.join(data_dir, storage_config.get('servers_file', 'servers.json'))
        )
        self.clients_storage = JSONStorage(
            os.path.join(data_dir, storage_config.get('clients_file', 'clients.json'))
        )
        
    async def get_models(self) -> List[ModelInfo]:
        """获取所有模型"""
        data = await self.models_storage.load()
        return [ModelInfo.from_dict(model_data) for model_data in data.get('models', [])]
        
    async def save_models(self, models: List[ModelInfo]):
        """保存模型列表"""
        data = {
            'models': [model.to_dict() for model in models],
            'last_update': time.time()
        }
        await self.models_storage.save(data)
        
    async def get_model_by_id(self, model_id: str) -> Optional[ModelInfo]:
        """根据ID获取模型"""
        models = await self.get_models()
        for model in models:
            if model.id == model_id:
                return model
        return None
        
    async def add_model(self, model: ModelInfo):
        """添加模型"""
        models = await self.get_models()
        models.append(model)
        await self.save_models(models)
        
    async def update_model(self, model: ModelInfo):
        """更新模型"""
        models = await self.get_models()
        for i, existing_model in enumerate(models):
            if existing_model.id == model.id:
                models[i] = model
                break
        await self.save_models(models)
        
    async def delete_model(self, model_id: str):
        """删除模型"""
        models = await self.get_models()
        models = [model for model in models if model.id != model_id]
        await self.save_models(models)

    async def get_subscriptions(self) -> List[SubscriptionRecord]:
        """获取所有订阅"""
        data = await self.subscriptions_storage.load()
        return [SubscriptionRecord.from_dict(sub_data) for sub_data in data.get('subscriptions', [])]

    async def save_subscriptions(self, subscriptions: List[SubscriptionRecord]):
        """保存订阅列表"""
        data = {
            'subscriptions': [sub.to_dict() for sub in subscriptions],
            'last_update': time.time()
        }
        await self.subscriptions_storage.save(data)

    async def get_subscription_by_id(self, subscription_id: str) -> Optional[SubscriptionRecord]:
        """根据ID获取订阅"""
        subscriptions = await self.get_subscriptions()
        for subscription in subscriptions:
            if subscription.id == subscription_id:
                return subscription
        return None

    async def add_subscription(self, subscription: SubscriptionRecord):
        """添加订阅"""
        subscriptions = await self.get_subscriptions()
        subscriptions.append(subscription)
        await self.save_subscriptions(subscriptions)

    async def update_subscription(self, subscription: SubscriptionRecord):
        """更新订阅"""
        subscriptions = await self.get_subscriptions()
        for i, existing_subscription in enumerate(subscriptions):
            if existing_subscription.id == subscription.id:
                subscriptions[i] = subscription
                break
        await self.save_subscriptions(subscriptions)

    async def delete_subscription(self, subscription_id: str):
        """删除订阅"""
        subscriptions = await self.get_subscriptions()
        subscriptions = [sub for sub in subscriptions if sub.id != subscription_id]
        await self.save_subscriptions(subscriptions)

    async def get_servers(self) -> List[SubscriptionServer]:
        """获取所有服务器"""
        data = await self.servers_storage.load()
        return [SubscriptionServer.from_dict(server_data) for server_data in data.get('servers', [])]

    async def save_servers(self, servers: List[SubscriptionServer]):
        """保存服务器列表"""
        data = {
            'servers': [server.to_dict() for server in servers],
            'last_update': time.time()
        }
        await self.servers_storage.save(data)

    async def get_server_by_id(self, server_id: str) -> Optional[SubscriptionServer]:
        """根据ID获取服务器"""
        servers = await self.get_servers()
        for server in servers:
            if server.id == server_id:
                return server
        return None

    async def add_server(self, server: SubscriptionServer):
        """添加服务器"""
        servers = await self.get_servers()
        servers.append(server)
        await self.save_servers(servers)

    async def update_server(self, server: SubscriptionServer):
        """更新服务器"""
        servers = await self.get_servers()
        for i, existing_server in enumerate(servers):
            if existing_server.id == server.id:
                servers[i] = server
                break
        await self.save_servers(servers)

    async def delete_server(self, server_id: str):
        """删除服务器"""
        servers = await self.get_servers()
        servers = [server for server in servers if server.id != server_id]
        await self.save_servers(servers)

    # 客户端管理方法
    async def get_clients(self) -> List[ClientInfo]:
        """获取所有客户端"""
        data = await self.clients_storage.load()
        return [ClientInfo.from_dict(client_data) for client_data in data.get('clients', [])]

    async def save_clients(self, clients: List[ClientInfo]):
        """保存客户端列表"""
        data = {
            'clients': [client.to_dict() for client in clients],
            'last_update': time.time()
        }
        await self.clients_storage.save(data)

    async def get_client_by_id(self, client_id: str) -> Optional[ClientInfo]:
        """根据ID获取客户端"""
        clients = await self.get_clients()
        for client in clients:
            if client.id == client_id:
                return client
        return None

    async def get_client_by_client_id(self, client_id: str) -> Optional[ClientInfo]:
        """根据client_id获取客户端"""
        clients = await self.get_clients()
        for client in clients:
            if client.client_id == client_id:
                return client
        return None

    async def add_client(self, client: ClientInfo):
        """添加客户端"""
        clients = await self.get_clients()
        clients.append(client)
        await self.save_clients(clients)

    async def update_client(self, client: ClientInfo):
        """更新客户端"""
        clients = await self.get_clients()
        for i, existing_client in enumerate(clients):
            if existing_client.id == client.id:
                clients[i] = client
                break
        await self.save_clients(clients)

    async def delete_client(self, client_id: str):
        """删除客户端"""
        clients = await self.get_clients()
        clients = [client for client in clients if client.id != client_id]
        await self.save_clients(clients)

    # 模型状态管理方法
    async def get_model_statuses(self) -> List[ModelStatusInfo]:
        """获取所有模型状态"""
        data = await self.clients_storage.load()  # 使用同一个存储文件
        return [ModelStatusInfo.from_dict(status_data) for status_data in data.get('model_statuses', [])]

    async def save_model_statuses(self, statuses: List[ModelStatusInfo]):
        """保存模型状态列表"""
        data = await self.clients_storage.load()
        data['model_statuses'] = [status.to_dict() for status in statuses]
        data['last_update'] = time.time()
        await self.clients_storage.save(data)

    async def get_model_statuses_by_client(self, client_id: str) -> List[ModelStatusInfo]:
        """根据客户端ID获取模型状态"""
        statuses = await self.get_model_statuses()
        return [status for status in statuses if status.client_id == client_id]

    async def add_model_status(self, status: ModelStatusInfo):
        """添加模型状态"""
        statuses = await self.get_model_statuses()
        statuses.append(status)
        await self.save_model_statuses(statuses)

    async def update_model_status(self, status: ModelStatusInfo):
        """更新模型状态"""
        statuses = await self.get_model_statuses()
        for i, existing_status in enumerate(statuses):
            if existing_status.id == status.id:
                statuses[i] = status
                break
        await self.save_model_statuses(statuses)

    async def delete_model_status(self, status_id: str):
        """删除模型状态"""
        statuses = await self.get_model_statuses()
        statuses = [status for status in statuses if status.id != status_id]
        await self.save_model_statuses(statuses)

    async def delete_model_statuses_by_client(self, client_id: str):
        """删除客户端的模型状态"""
        statuses = await self.get_model_statuses()
        statuses = [status for status in statuses if status.client_id != client_id]
        await self.save_model_statuses(statuses)


# 全局数据管理器实例
data_manager = DataManager()
